package com.example.demo04plc.service;

import HslCommunication.Core.Types.OperateResult;
import com.example.demo04plc.plc.common.*;
import com.example.demo04plc.plc.modbus.tcp.ModbusTcpConnection;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.PreDestroy;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@Slf4j
@RequiredArgsConstructor
public class PlcConnectionServiceImpl implements PlcConnectionService {
    private final PlcDeviceStatusListener plcDeviceStatusListener;
    private final Map<String, PlcConnection> PLC_CONNECTION = new HashMap<>();
    private boolean reportDeviceStatus;

    @PreDestroy
    public void destroy() {
        Iterator<Map.Entry<String, PlcConnection>> iterator = PLC_CONNECTION.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, PlcConnection> plcConnectionEntry = iterator.next();
            plcConnectionEntry.getValue().close();
            iterator.remove();
        }
    }

    @Override
    public PlcConnection getConnection(String deviceId, String connectionString, boolean reportDeviceStatus) {
        this.reportDeviceStatus = reportDeviceStatus;
        return PLC_CONNECTION.computeIfAbsent(deviceId, key -> {
            PlcConnectionConfig connectionConfig = PlcConnectionConfig.parse(connectionString);
            String transport = connectionConfig.getTransport();
            PlcConnection plcConnection;
            switch (transport) {
                case "modbus-tcp":
                    plcConnection = new ModbusTcpConnection(deviceId);
                    break;
                default:
                    throw new IllegalStateException("Unexpected value: " + transport);
            }
            OperateResult result = plcConnection.connect(connectionConfig);
            if (result.IsSuccess) {
                log.info("设备[{}]{}连接成功", deviceId, transport);
                if (reportDeviceStatus) {
                    plcDeviceStatusListener.onDeviceConnect(deviceId);
                }
            } else {
                log.error("设备[{}]{}连接失败", deviceId, transport);
            }
            return plcConnection;
        });
    }


    @Override
    public void closeConnection(String deviceId) {
        PlcConnection plcConnection = PLC_CONNECTION.get(deviceId);
        if (plcConnection.isConnected()) {
            plcConnection.closeScheduleRead();
            OperateResult result = plcConnection.close();
            if (result.IsSuccess) {
                log.info("设备[{}]{}关闭连接成功", deviceId, plcConnection.getConnectionConfig().getTransport());
                PLC_CONNECTION.remove(deviceId);
                if (reportDeviceStatus) {
                    plcDeviceStatusListener.onDeviceClose(deviceId);
                }
            } else {
                log.error("设备[{}]{}关闭连接失败，{}", deviceId, plcConnection.getConnectionConfig().getTransport(), result.Message);
            }
        }
    }
}
